'use strict'

const path = require('path')
const fs = require('fs')
const isXfce = require('is-xfce')
const { app, Notification, BrowserWindow, dialog } = require('electron')
const electronLocalShortcut = require('electron-localshortcut')
const log4js = require('log4js')

const AppConfig = require('../configuration')
const MenuHandler = require('./lib/menu')

const CSSInjector = require('../renderer/lib/css')
const MessageHandler = require('./lib/message')

let Common = (AppConfig.readSettings('language') === 'zh_CN') ? require('../common_cn') : require('../common')

class WeChatWindow {
  constructor() {
    this.isShown = false
    this.loginState = { NULL: -2, WAITING: -1, YES: 1, NO: 0 }
    this.loginState.current = this.loginState.NULL
    this.inervals = {}
    this.splashWindow = null
    this.logger = log4js.getLogger("WECHAT")
    this.logger.level = AppConfig.readSettings("logger-level")
    this.createWindow()
    this.initWechatWindowShortcut()
    this.initWindowEvents()
    this.initWindowWebContent()
  }

  resizeWindow(isLogged, splashWindow) {
    this.logger.debug(`resize window`, this.loginState.current)

    if (this.loginState.current === this.loginState.WAITING) {
      splashWindow.close()
      this.show()
      this.wechatWindow.center()
      this.loginState.current = this.loginState.NO
    } else {
      let size = isLogged ? AppConfig.readSettings("window-size") : Common.WINDOW_SIZE_LOGIN
      this.logger.debug(`current: ${this.loginState.current}, isLogged: ${isLogged}, size: ${JSON.stringify(size)}`)
      if (isLogged || this.loginState.current) {
        this.wechatWindow.setResizable(true)
        this.wechatWindow.center()
        this.wechatWindow.setSize(size.width, size.height)
        this.wechatWindow.setResizable(isLogged)
        this.loginState.current = isLogged
        if ( this.wechatWindow.isMinimized() || !this.wechatWindow.isVisible() ) {
          this.wechatWindow.show()
        } else if ( this.wechatWindow.isMaximized() ) {
          this.wechatWindow.unmaximize()
        }
      }
    }
  }

  createWindow() {
    this.logger.debug("create window")
    this.wechatWindow = new BrowserWindow({
      title: Common.ELECTRONJS_WECHAT,
      resizable: false,
      center: true,
      show: false,
      width: Common.WINDOW_SIZE_LOGIN.width,
      height: Common.WINDOW_SIZE_LOGIN.height,
      frame: true,
      autoHideMenuBar: true,
      icon: path.join(__dirname, '../renderer/assets/icon.png'),
      titleBarStyle: 'customButtonsOnHover',
      transparent: true,
      backgroundColor: "#ffffff",
      webPreferences: {
        javascript: true,
        plugins: true,
        nodeIntegration: true,
        contextIsolation: false,
        webSecurity: true,
        preload: path.join(__dirname, '../renderer/lib/preload.js'),
      },
    })

    /* menu is always visible on xfce session */
    isXfce.then(data => {
      if(data) {
        this.wechatWindow.setMenuBarVisibility(true)
        this.wechatWindow.setAutoHideMenuBar(false)
      }
    })

    new MenuHandler().create()
  }

  loadURL(url) {
    this.logger.debug(`load url: ${url}`)
    this.wechatWindow.loadURL(url)
  }

  reload() {
    this.logger.debug("reload webContents")
    this.wechatWindow.reload()
  }

  show() {
    this.logger.debug("show window")
    this.wechatWindow.show()
    this.wechatWindow.focus()
    this.wechatWindow.webContents.send('show-wechat-window')
    this.isShown = true
  }

  hide() {
    this.logger.debug("hide window")
    this.wechatWindow.hide()
    this.wechatWindow.webContents.send('hide-wechat-window')
    this.isShown = false
  }

  connectWeChat() {
    this.logger.debug("connect wechat")
    Object.keys(this.inervals).forEach((key, index) => {
      clearInterval(key)
      delete this.inervals[key]
    })

    this.loadURL(Common.WEB_WECHAT)
    const int = setInterval(() => {
      if (this.loginState.current === this.loginState.NULL) {
        this.loadURL(Common.WEB_WECHAT)
        this.logger.debug("reconnect wechat")
      }
    }, 5000)
    this.inervals[int] = true
  }

  initWindowWebContent() {
    this.wechatWindow.webContents.setUserAgent(Common.USER_AGENT[process.platform])
    if (Common.DEBUG_MODE) {
      this.wechatWindow.webContents.openDevTools()
    }

    this.connectWeChat()

    this.wechatWindow.webContents.on('will-navigate', (event, url) => {
      if(/((.*)\.)?wx(2)?\.qq\.com/.test(url)) {
        this.logger.debug("wx: ", url)
        return
      } else if(/(login|mp).weixin\.qq\.com/.test(url)) {
        this.logger.debug("weixin: ", url)
        return
      } else if(/js\.aq\.qq\.com/.test(url)) {
        this.logger.debug("js: ", url)
        return
      } else if(/mmbiz\.qpic\.cn/.test(url)) {
        this.logger.debug("mmbiz: ", url)
        return
      } else {
        this.logger.debug(url)
        event.preventDefault()
      }
    })

    this.wechatWindow.webContents.setWindowOpenHandler((details) => {
      if(details.url.startsWith('https://file.wx2.qq.com/')) {
        this.logger.debug("deny open new window: ")
        this.wechatWindow.webContents.downloadURL(details.url)
        return {action: "deny"}
      } else {
        this.logger.debug("refuse open: ", details.url)
        return {action: "deny"}
      }
    })

    this.wechatWindow.webContents.on('dom-ready', () => {
      this.wechatWindow.webContents.insertCSS(CSSInjector.commonCSS)
      if (process.platform === 'darwin') {
        this.wechatWindow.webContents.insertCSS(CSSInjector.osxCSS)
      }
    })

    this.wechatWindow.webContents.session.on('will-download', (event, item, webCont) => {
      this.logger.debug("download: ", item.getURL())
      let notify = {}
      let home = process.platform === 'win32' ? process.env.USERPROFILE : process.env.HOME
      let downloadDir = path.join(home, AppConfig.readSettings("download-dir"))

      notify.title = "Wechat Download Info"

      item.once('done', (event, state) => {
        if(state === 'completed') {
          notify.body = `${item.getFilename()} ${state}`
          new Notification(notify).show()
        } else {
          notify.body = `${item.getFilename()} ${state}`
          new Notification(notify).show()
        }
      })

      if(!fs.existsSync(downloadDir)) {
        fs.mkdir(downloadDir, {recursive: true}, (error) => {
          if(error) {
            notify.body = error
            new Notification(notify).show()
            this.logger.fatal(error)
          }
        })
      }

      item.setSaveDialogOptions({
        title: Common.FILE_SAVE_DIALOGTITLE,
        filters: [
          { name: 'Text', extensions: ['txt', 'csv'] },
          { name: 'Script', extensions: ['sh', 'js', 'py', 'pl', 'go', 'lua', 'cmd', 'bat'] },
          { name: 'Images', extensions: ['jpg', 'png', 'gif'] },
          { name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
          { name: 'Documents', extensions: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'] },
          { name: 'Compress File', extensions: ['tar', 'gz', 'tgz', 'xz', 'bz', 'bz2', 'xb', 'qp', 'zip', 'rar', '7z'] },
          { name: 'All Files', extensions: ['*'] }
        ],
        defaultPath: path.join(downloadDir, item.getFilename())
      })
    })

    this.wechatWindow.webContents.on('did-create-window', (childWindow) => {
      this.logger.debug("open new window")
      childWindow.webContents.session.on('will-download', (event, item, webCont) => {
        this.logger.debug("download: ", item.getURL())
        let filePath = path.join(process.env.HOME, 'tmp', item.getFilename())
        item.setSavePath(filePath)
      })
    })

  }

  initWindowEvents() {
    this.wechatWindow.on('close', (e) => {
      this.logger.debug("触发: Ctrl+Q")
      this.unregisterLocalShortCut()
    })

    this.wechatWindow.on('closed', (event, isAlwaysOnTop) => {
      this.wechatWindow = null
    })

    this.wechatWindow.on('page-title-updated', (event) => {
      if (this.loginState.current === this.loginState.NULL) {
        this.loginState.current = this.loginState.WAITING
      }
      event.preventDefault()
    })

    this.wechatWindow.on('show', () => {
      this.registerLocalShortcut()
    })
  }

  registerLocalShortcut() {
    this.logger.debug("register localshortcut")
    electronLocalShortcut.register(this.wechatWindow, [(process.platform === 'darwin') ? 'Cmd+H': 'Ctrl+H'], () => {
      this.hide()
    })
  }

  unregisterLocalShortCut() {
    this.logger.debug("unregister localshortcut")
    electronLocalShortcut.unregisterAll(this.wechatWindow)
  }

  initWechatWindowShortcut() {
    this.registerLocalShortcut()
  }
}

module.exports = WeChatWindow
